<?php
/* 
老的数据库连接方式
		'cis' => array(
			'type' => 'mysql',
			'host' => 'localhost',
			'port' => '3306',
			'user' => 'root',
			'password' => 'sa',
			'db' => 'winhidb_news',
			'prefix' => 'winhi_',
			'debug' => '1',
			'charset' => 'utf8'
		)
  */
class EDatabaseMySQL extends EObject {
	var $connectionId; //连接指针
	var $prefix='';
	var $database;
	var $options=array();//数据库连接配置
	var $fetchMode; //返回的结果模式asscoc,num,both
	var $result; //查询结果
	var $_state;//当前状态: 查询结果类型(boolen,source),插入ID $insertId，影响行数$affectedRows， 结果行数$numRows
	var $query_times = 0; //数据库查询次数
	var $_hasQuoted = false;//是否被引用
	var $_quoted = array();
	var $path; //路径
	var $debug = 1;//调试
	var $pointer = 0;
	var $charset='utf8';
	var $_history = array ();

	function __construct($options){
		$this->setFrom($options);
		$this->options=$options;
		if (!function_exists( 'mysql_connect' )){
			trigger_error('The MySQL adapter "mysql" is not available.',E_USER_ERROR);
		}
		$this->connect($options);
	 
		if (strpos($this->getVersion(),'5' )=== 0){
			$this->query("set names '".$this->charset."'");
		}
	}
	function connect($options,$forcenew=true){
		
		if(empty($options))return false;
	 
		if($options['port'])$options['host'].=':'.$options['port'];
		$this->connectionId = mysql_connect($options['host'],$options['user'],$options['password'],$forcenew);
		if(is_resource($this->connectionId)){
			if($this->selectDB($options['database'])){
				$this->prefix=$options['prefix'];
				return true;
			}else{
				trigger_error('Could not connect to database: '.$this->database,E_USER_ERROR);
				return false;
			}
		}else{
			trigger_error('Could not connect to MySQL',E_USER_ERROR);
			return false;
		}
	}
	function selectDB($dbname) {
		if ($this->connectionId === false) {
			return false;
		} else {
			if(mysql_select_db($dbname, $this->connectionId)){
				$this->database = $dbname;
				return true;
			}else{
				trigger_error('Could not connect to Database:'.$dbname,E_USER_ERROR);
				return false;
			}
		}
	}
	function getVersion() {
		return mysql_get_server_info();//$this->connectionId
	}
	function getPrefix(){
		return $this->prefix;
	}
	function getNumRows() {
		return $this->_state['num_rows'];
	}
	function IsConnected() {
		return !empty ($this->connectionId);
	}
	function getInsertid() {
		return $this->_state['insert_id'];
	}
	function SetFetchMode($mode = '') {
		switch ($mode) {
			case MYSQL_NUM :
				$this->fetchMode = MYSQL_NUM;
				break;
			case MYSQL_ASSOC :
				$this->fetchMode = MYSQL_ASSOC;
				break;
			case MYSQL_BOTH :
				$this->fetchMode = MYSQL_BOTH;
				break;
			default :
				$this->fetchMode = MYSQL_ASSOC;
				break;
		}
	}
	function & query($strQuery=null) {
		$this->setQuery($strQuery);
		$this->_state=array();
		$this->_state['query']=$strQuery;
		if (is_resource($this->result))	mysql_free_result($this->result);//清空前一个结果集
		$this->result = mysql_query($strQuery, $this->connectionId);
		$this->query_times++;
		$this->_state['type']=gettype($this->result);
		if($this->result===true){
			//debug($this->result,mysql_insert_id());
			if($id=mysql_insert_id($this->connectionId)){
				$this->_state['insert_id']=$id;
				$this->result=$id;
			}
			$this->_state['affected_rows']=mysql_affected_rows($this->connectionId);
			if($this->debug)$this->_debug();
			return $this->result;//为引用，不能 return true;
		}elseif($this->_state['type']==='resource'){
			$this->_state['num_rows']= mysql_num_rows($this->result);
			if($this->debug)$this->_debug();
			return $this->result;
		}elseif($this->result===false){
			$this->_state['error']=sprintf("MySQL Error[%s]:%s<br>Query String:$strQuery", mysql_errno(),mysql_error());
			if($this->debug)$this->_debug();
			return trigger_error($this->_state['error'], E_USER_ERROR);
		}else{
			$this->_state['error']=sprintf('MySQL Error returned not false Error[%s]:%s<br>Query String:'.$strQuery, mysql_errno(),mysql_error());
			if($this->debug)$this->_debug();
			return trigger_error('MySQL Error['.mysql_errno().']:'.mysql_error(), E_USER_ERROR);
		}
	}
	function & setQuery(&$strQuery){
		if(!empty($strQuery)){
			$strQuery=str_replace('`#__','`'.$this->prefix,$strQuery);
			$this->_setQuery=&$strQuery;
			return $strQuery;
		}else{
			$strQuery=$this->_setQuery;
			return $strQuery;
		}
	}
	function _debug(){
		if(!$this->debug)return;
		$this->_history[$this->pointer]=$this->_state;
		$this->pointer++;
	}
	/**
	* This global function loads the first row of a query into an object
	*
	* return object
	*/
	function &loadObject($strQuery=null)
	{
		$this->query($strQuery);
		if(is_resource($this->result)){
			$object = mysql_fetch_object( $this->result );
			mysql_free_result( $this->result);
			return $object;
		}else{
			return false;
		}
	}
	/**
	* Load a list of database objects
	* @param string The field name of a primary key
	* @return array If <var>key</var> is empty as sequential list of returned records.
	* If <var>key</var> is not empty then the returned array is indexed by the value
	* the database key.  Returns <var>null</var> if the query fails.
	*/
	function &loadObjectList( $strQuery=null,$key='' )
	{
		$this->query($strQuery);
		$array = array();
		if($key){
			while ($row = mysql_fetch_object( $this->result )) {
				$array[$row->$key] = $row;
			}
			return $array;
		}else{
			while ($array[] = mysql_fetch_object( $this->result )); 
			array_pop($array);
		}
		mysql_free_result( $this->result );
		return $array;
	}
	/**
	* Fetch a result row as an associative array
	*
	* return array
	*/
	function &LoadAssoc($strQuery=null,$fetchMode=MYSQL_ASSOC){
		$this->Query($strQuery);
		if(is_resource($this->result)){
			$rs=mysql_fetch_array($this->result,$fetchMode);
			mysql_free_result($this->result);
		}else{
			return false;
		}
		return $rs;
	}
	/**
	* Load a assoc list of database rows
	* @param string The field name of a primary key
	* @return array If <var>key</var> is empty as sequential list of returned records.
	*/
	function &LoadAssocList($strQuery=null,$key='',$fetchMode=MYSQL_ASSOC){
		$this->Query($strQuery);
		if($key){
			while($row = mysql_fetch_assoc($this->result))
				$rs[$row[$key]]=$row;
			mysql_free_result($this->result);
			return $rs;
		}else{
			while ($rs[] = mysql_fetch_array($this->result, $fetchMode));
			array_pop($rs);
			mysql_free_result($this->result);
			return $rs;
		}
	}
	/**
	* This method loads the first field of the first row returned by the query.
	*
	* @return The value returned in the query or null if the query failed.
	*/
	function LoadResult($strQuery){
		$rs=$this->LoadAssoc($strQuery,MYSQL_NUM);
		if(isset($rs[0]))return $rs[0];
		return $rs;
	}
	function FilterList($table,$arrFilters,$return_fields='*',$sort=null){
		if (is_array($arrFilters)) {
			$tj = "\nWHERE ".implode(' AND ',$arrFilters);
/*			foreach ($arrFilters as $key => $value) {
				$tj .= '`' . $key . '`=\'' . $value . '\' and ';
			}
			$tj = substr($tj, 0, -4);
			*/
		}elseif(is_string($arrFilters)){
			$tj = ' where ' .$arrFilters;
		}
		if ($sort){
			$sort = "\n ORDER BY " . $sort;
		}
		$strQuery = 'select ' . $return_fields . ' from `#__'. $table . '` ' . $tj . $sort;
		//debug($tj,$strQuery);
		return $this->LoadAssocList($strQuery);
	}
	function _insert_assoc($table, $array) {
		if (!$array OR !is_array($array))
			return false;
		$fields = '(';
		$values = '(';
		foreach ($array as $key => $value) {
			if (is_array($value)) {
				$this->insert_assoc[$key] = $value;
			} else {
				$fields .= '`' . $key . '`,';
				if ($value === 'now()'){
					$values .= 'now(),';
				}else{
					$values .= '\'' . $value . '\',';
				}
			}
		}
		$fields = substr($fields, 0, -1) . ')';
		$values = substr($values, 0, -1) . ')';
		$strQuery = 'insert into `#__' . $table . '` ' . $fields . ' values ' . $values;
		//debug($strQuery);
		return $this->query($strQuery);
	}
	/**
	 * 插入多条记录
	 */
	function insertList($table,$array,$pk='id'){
		if(!is_array($array) || !$table)return false;
		$flag=true;
		foreach($array as $value){
			if(!is_array($value))continue;
			if(!$this->insert($table,$value)){
				$flag=false;
				trigger_error('插入记录错误!'.implode(',',$value),E_USER_WARRNING);
				break;
			}
		}
		return $flag;
	}
	/**
	 * 插入一条记录，支持关联表

	 */
	function insert($table, $array, $pk='id') {
		if(!is_array($array) || !$table)return false;
		$rs = $this->_insert_assoc($table, $array,$pk);
		$flag=false;
		if ($rs) {
			$id=$this-> getInsertid();
			if ($id && !empty($this->insert_assoc)){
				$foreignKey = $table . '_id';
				//$this->insert_assoc[$foreignKey]=$this-> getInsertid();
				foreach ($this->insert_assoc as $key => $value) {
					$value[$foreignKey] = $this-> getInsertid();
					$rs_assoc=$this->_insert_assoc($key, $value);
					if(!$rs_assoc){
						$this->error[]='Error inert (Table Assoc: '.$key.').';
						$flag=true;
					}
				}
				return $id;
			} else 
				return $id;
		} else {
			$this->error[] = 'Error Insert:( Table:'.$table.')';
			return false;
		}
	}
	/**
	* Document::db_insertObject()
	*
	* { Description }
	*
	* @param [type] $keyName
	* @param [type] $verbose
	*/
	function insertObject( $table, &$object, 
	$keyName = NULL, $verbose=false )
	{
		$fields = array();
		foreach (get_object_vars( $object ) as $k => $v) {
			if (is_array($v) or is_object($v) or $v === NULL) {
				continue;
			}
			if ($k[0] == '_') { // internal field
				continue;
			}
			$fields[] = $this->NameQuote( $k );;
			$values[] = $this->isQuoted( $v ) ? $this->Quote( $v ) : $v;
		}
		$strQuery=sprintf("INSERT INTO `%s` ( %s ) VALUES ( %s ) ",$object->getTableName(),implode( ",", $fields ),implode( ",", $values ));
		($verbose) && print "$sql<br />\n";
		if (!$this->query($strQuery)) {
			return false;
		}
		$id = $this->insertid();
		//如果如果上一查询没有产生 AUTO_INCREMENT 的值，则 mysql_insert_id() 返回 0
		if ($keyName && $id) {
			$object->$keyName = $id;
		}
		return true;
	}
	function &getByPk($table,$id,$pk='id'){
		$strQuery='select * from `#__'.$table.'` where `'.$pk.'`='.$id;
		$rs=$this->LoadAssoc($strQuery);
		return $rs;
	}
	/**
	 * 支持多条记录同时更新
	 * 
	 */
	function updateList($table,$array,$primaryKey='id'){
		if(!is_array($array) || !$table)return false;
		$flag=true;
		foreach($array as $value){
			if(!is_array($value))continue;
			if(!$this->update($table,$value,$primaryKey)){
				$flag=false;
				trigger_error('更新错误',E_USER_WARRNING);
				break;
			}
		}
		return $flag;	
	}
	/**
	 * 更新关联的表
	 */
	function update($table, $array,$primaryKey='id') {
		if(!$array || !$table){return false;}
		$tj = 'where `'.$primaryKey.'`=' . $array[$primaryKey];
		//if($array['id'] and $primaryKey!='id')$tj.=' and `id`='.$array['id'];
		//unset($array[$primaryKey]);
		$setdata = '';
		foreach ($array as $key => $value) {
			$error=false;
			if (is_array($value)) {
				$pk=$table . '_'.$primaryKey;//getByPk
				$value[$pk]=$array[$primaryKey];
				$exists_check=$this->getByPk($key,$value[$pk],$pk);
				if($exists_check){
					$rs=$this->update($key, $value, $pk);
				}else{
					$rs=$this->insert($key, $value, $pk);
				}
				if(!$rs){
				    $this->_state['error']='update table ['.$key.'] error.';
				    $error=true;
				}
			} else {
				if($value==='now()'){
					$setdata .= "`$key`=$value,";
				}else{
					$setdata .= "`$key`='$value',";
				}
			}
		}
		$strQuery = 'update `#__'. $table . '` set ' . substr($setdata, 0, -1).' '. $tj;
		$rs=$this->query($strQuery);
		return !$error && $rs;
	}
	
	/**
	 * Document::db_updateObject()
	 * @param [type] $updateNulls
	 */
	function updateObject( $table, &$object, $keyName, $updateNulls=true )
	{
		$strQuery = "UPDATE $table SET %s WHERE %s";
		$tmp = array();
		foreach (get_object_vars( $object ) as $k => $v) {
			if( is_array($v) or is_object($v) or $k[0] == '_' ) {// internal or NA field
				continue;
			}
			if( $k == $keyName ) { // PK not to be updated
				$where = $keyName . '=' . $this->Quote( $v );
				continue;
			}
			if ($v === NULL && !$updateNulls) {
				continue;
			}
			if( $v == '0' ) {
				$val = $this->isQuoted( $v ) ? $this->Quote( '0' ) : 0;
			} else if( $v == '' ) {
				$val = $this->isQuoted( $v ) ? $this->Quote( '' ) : 0;
			} else {
				$val = $this->isQuoted( $v ) ? $this->Quote( $v ) : $v;
			}
			$tmp[] = $this->NameQuote( $k ) . '=' . $val;
		}
		$strQuery=sprintf("UPDATE `%s` SET %s WHERE %s", $table,implode( ",", $tmp ) , $where );
		return $this->query($strQuery);
	}
	/**
	 * Checks if field name needs to be quoted
	 *
	 * @access public
	 * @param string The field name
	 * @return bool
	 */
	function isQuoted( $fieldName )
	{
		if ($this->_hasQuoted) {
			return in_array( $fieldName, $this->_quoted );
		} else {
			return true;
		}
	}
	/**
	* Get a quoted database escaped string
	*
	* @access public
	* @return string
	*/
	function Quote( $text ) {
		return '\'' . $text . '\'';
	}
	/**
	 * Quote an identifier name (field, table, etc)
	 *
	 * @access public
	 * @param string The name
	 * @return string The quoted name
	 */
	function NameQuote($s,$q='`') {
		if (strlen( $q ) == 1) {
			return $q . $s . $q;
		} else {
			return $q{0} . $s . $q{1};
		}
	}
	function getFields($arrFieldsDesc = array ()) { //添加字段描述语言
		$i = 0;
		while ($field = mysql_fetch_field($this->result)) {
			//$this->fields[]=$field;//取字段所有信息(长度，大小，字段名..........)
			$namelen = strlen($this->fields[$i]['name'] = $field->name);
			$fieldlen = $field->max_length;
			$this->fields[$i]['length'] = (($namelen > $fieldlen) ? $namelen : $fieldlen);
			$this->fields[$i]['type'] = $field->type;
			if ($arrFieldsDesc)
				$this->fields[$i]['desc'] = $arrFieldsDesc[$field->name];
			else
				$this->fields[$i]['desc'] = $field->name;
			$i++;
		}
		return $this->fields;
	}

	function & Execute($sql, $nrows = -1, $offset = -1, $inputarr = false, $secs2cache = 0) {
		$limit = '';
		if ($offset != -1 || $nrows != -1) {
			$offset = ($offset >= 0) ? $offset . "," : '';
			$limit = ' LIMIT ' . $offset . ' ' . $nrows;
		}
		$this->result = @ mysql_query($sql . $limit, $this->connectionId);
		$this->type_rs = gettype($this->result);
		$this->query_times++;
		if ($this->type_rs === 'boolean') {
			return $this->result;
		}
		elseif ($this->type_rs === 'resource') {
			include_once ($this->path . 'leoDBResultSet.php');
			$rs = new mysqlResultSet($this->result, $this->connectionId);
			$rs->_currentRow = 0;
			$rs->sql = $sql;
			$rs->fetchMode = $this->fetchMode;
			if ($rs->_fetch()) {
				return $rs;
			} else {
				return false;
			}
		} else {
			return false;
		}
	}

	function & splitPage($query=null, $page = 1, $max_rows = 20, $limit = 0, $getfields = false) {
		if(empty($query)){
			$query=$this->_setQuery;
		}
		$this->queryString = $query;
		$page =empty($page)?1:intval($page);
		$this->splits=array();
		$this->splits['current'] = $page;
		$this->splits['pageSize'] = intval($max_rows);
		$pos_to = strlen($this->queryString);
		$pos_from = strpos($this->queryString, ' from', 0);
		if ($pos_from === false)
			$pos_from = strpos($this->queryString, ' FROM', 0);
		$countString = 'select count(*) as total ' . substr($this->queryString, $pos_from, ($pos_to - $pos_from));
		$rs = $this->query($countString);
		if ($rs) {
			$rs = mysql_fetch_array($rs, MYSQL_ASSOC);
			$this->splits['matches'] = $rs['total'];
		} else {
			return false;
		}
		if ($limit && $limit < $rs['total']) {
			$this->splits['nums'] = $limit;
		} else {
			$this->splits['nums'] = $rs['total'];
		}
		$this->splits['total'] = ceil($this->splits['nums'] / $this->splits['pageSize']);
		if ($this->splits['current'] > $this->splits['total']) {
			$this->splits['current'] = ($this->splits['total'])?$this->splits['total']:1;
		}
		if ($this->splits['current'] > 1) {
			$this->splits['first'] = 1;
			$this->splits['prev'] = $this->splits['current'] - 1;
		} else {
			$this->splits['first'] = false;
			$this->splits['prev'] = false;
		}
		if ($this->splits['current'] < $this->splits['total']) {
			$this->splits['next'] = $this->splits['current'] + 1;
			$this->splits['last'] = $this->splits['total'];
		} else {
			$this->splits['next'] = false;
			$this->splits['last'] = false;
		}
		if ($this->splits['total'] < 12) {
			$this->splits['numberlink'] = range(1, $this->splits['total']);
		} else {
			if ($this->splits['current'] < 7) {
				$this->splits['numberlink'] = range(1, 11);
			}elseif ($this->splits['current'] + 5 >= $this->splits['total']) {
				$start = $this->splits['total'] - 10;
				$this->splits['numberlink'] = range($start, $this->splits['total']);
			} else {
				$this->splits['numberlink'] = range($this->splits['current'] - 5, $this->splits['current'] + 5);
			}
		}
		$offset = ($this->splits['pageSize'] * ($this->splits['current'] - 1));
		$limitStr = ' LIMIT ' . $offset . ',' . $this->splits['pageSize'];
		$this->queryString .= $limitStr;
		$rs=$this->LoadAssocList($this->queryString);
		return $rs;
	}
	function Close() {
		//$this->__destruct();
		if(is_resource($this->result))mysql_free_result($this->result);
		if(is_resource($this->connectionId))mysql_close($this->connectionId);
		$this->connectionId = false;
	}
	function __destruct() {

	}
}
?>